package com.gobang.gobang;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;

public class GobangServer {
    public static final int PORT = 9999;
    private ServerSocket serverSocket;
    private final Map<String, Room> rooms = new ConcurrentHashMap<>();
    private final Map<Socket, ClientHandler> clients = new ConcurrentHashMap<>();
    private final ExecutorService pool = Executors.newCachedThreadPool();
    private volatile boolean isRunning = false;
    
    public void start() {
        try {
            serverSocket = new ServerSocket(PORT);
            isRunning = true;
            log("服务器启动，等待玩家连接...");
            
            while (isRunning) {
                Socket clientSocket = serverSocket.accept();
                ClientHandler handler = new ClientHandler(clientSocket);
                clients.put(clientSocket, handler);
                pool.execute(handler);
                log("新客户端连接: " + clientSocket.getInetAddress().getHostAddress());
            }
        } catch (IOException e) {
            log("服务器错误: " + e.getMessage());
        }
    }
    
    private class ClientHandler implements Runnable {
        private final Socket socket;
        private final BufferedReader in;
        private final PrintWriter out;
        private String playerName;
        private Room currentRoom;
        
        public ClientHandler(Socket socket) throws IOException {
            this.socket = socket;
            this.in = new BufferedReader(
                new InputStreamReader(socket.getInputStream(), "UTF-8")
            );
            this.out = new PrintWriter(
                new OutputStreamWriter(socket.getOutputStream(), "UTF-8"),
                true
            );
        }
        
        @Override
        public void run() {
            try {
                String message;
                while ((message = in.readLine()) != null) {
                    handleMessage(message);
                }
            } catch (IOException e) {
                handleClientDisconnect();
            }
        }
        
        private void handleMessage(String message) {
            String[] parts = message.split("\\|");
            String command = parts[0];
            
            switch (command) {
                case "LOGIN":
                    playerName = parts[1];
                    sendRoomList();
                    break;
                    
                case "CREATE_ROOM":
                    String roomName = parts[1];
                    String roomId = UUID.randomUUID().toString();
                    Room newRoom = new Room(roomId, roomName, socket, playerName);
                    rooms.put(roomId, newRoom);
                    currentRoom = newRoom;
                    broadcastRoomList();
                    break;
                    
                case "JOIN_ROOM":
                    String joinRoomId = parts[1];
                    Room room = rooms.get(joinRoomId);
                    if (room != null && room.canJoin()) {
                        room.addPlayer(socket, playerName);
                        currentRoom = room;
                        broadcastRoomList();
                        if (room.isFull()) {
                            startGame(room);
                            // 立即发送当前比分给新加入的玩家
                            String score = room.getScoreInfo();
                            ClientHandler newPlayer = clients.get(socket);
                            if (newPlayer != null) {
                                newPlayer.out.println("SCORE|" + score);
                            }
                        }
                    }
                    break;
                    
                case "GET_ROOMS":
                    sendRoomList();
                    break;
                    
                case "MOVE":
                    if (currentRoom != null) {
                        if (parts[1].equals("WIN")) {
                            // 更新比分，根据胜者颜色判断
                            String winnerColor = parts[2];
                            Socket winner = socket;  // 发送胜利消息的玩家就是胜利者
                            
                            // 验证胜利者的颜色是否正确
                            if (("BLACK".equals(winnerColor) && winner.equals(currentRoom.getPlayer1())) ||
                                ("WHITE".equals(winnerColor) && winner.equals(currentRoom.getPlayer2()))) {
                                // 更新胜利者的分数
                                currentRoom.incrementScore(winner);
                                // 广播新的比分给房间内所有玩家
                                String score = currentRoom.getScoreInfo();
                                broadcastToRoom(currentRoom, "SCORE|" + score, null);
                                // 广播简单的胜利消息给对手
                                broadcastToRoom(currentRoom, "MOVE|WIN", socket);
                                // 广播新的房间状态
                                broadcastRoomList();
                            }
                        } else if (parts[1].equals("RESTART")) {
                            // 重置游戏状态
                            currentRoom.setGameStarted(true);
                            // 通知双方游戏重新开始
                            ClientHandler player1 = clients.get(currentRoom.getPlayer1());
                            ClientHandler player2 = clients.get(currentRoom.getPlayer2());
                            if (player1 != null) {
                                player1.out.println("GAME_START|BLACK");
                            }
                            if (player2 != null) {
                                player2.out.println("GAME_START|WHITE");
                            }
                            // 不需要广播 RESTART 消息，因为已经通过 GAME_START 通知了
                        } else {
                            // 只有普通的移动消息才需要广播给对手
                            broadcastToRoom(currentRoom, message, socket);
                        }
                    }
                    break;
                    
                case "LEAVE_ROOM":
                    if (currentRoom != null) {
                        // 通知另一个玩家
                        Socket otherPlayer = socket.equals(currentRoom.getPlayer1()) ? 
                            currentRoom.getPlayer2() : currentRoom.getPlayer1();
                        if (otherPlayer != null) {
                            ClientHandler otherHandler = clients.get(otherPlayer);
                            if (otherHandler != null) {
                                otherHandler.out.println("OPPONENT_LEFT");
                            }
                        }
                        // 处理退出
                        leaveCurrentRoom();
                    }
                    break;
                    
                case "GET_SCORE":
                    if (currentRoom != null) {
                        String score = currentRoom.getScoreInfo();
                        out.println("SCORE|" + score);
                    }
                    break;
            }
        }
        
        private void handleClientDisconnect() {
            leaveCurrentRoom();
            clients.remove(socket);
            try {
                socket.close();
            } catch (IOException e) {
                log("关闭socket错误: " + e.getMessage());
            }
        }
        
        private void leaveCurrentRoom() {
            if (currentRoom != null) {
                currentRoom.removePlayer(socket);
                // 只有当房间完全空了才移除房间
                if (currentRoom.getPlayer1() == null) {
                    rooms.remove(currentRoom.getRoomId());
                }
                currentRoom = null;
                broadcastRoomList();
            }
        }
        
        private void sendRoomList() {
            StringBuilder sb = new StringBuilder("ROOM_LIST|");
            for (Room room : rooms.values()) {
                sb.append(room.getRoomId()).append(",")
                  .append(room.getRoomName()).append(",")
                  .append(room.getPlayer1Name()).append(",")
                  .append(room.getPlayer2Name() == null ? "" : room.getPlayer2Name()).append(",")
                  .append(room.getStatus()).append(";");
            }
            out.println(sb.toString());
        }
        
        private void broadcastRoomList() {
            for (ClientHandler handler : clients.values()) {
                handler.sendRoomList();
            }
        }
        
        private void broadcastToRoom(Room room, String message, Socket sender) {
            if (sender == null) {
                // 如果sender为null，广播给房间内所有玩家
                ClientHandler player1Handler = clients.get(room.getPlayer1());
                ClientHandler player2Handler = clients.get(room.getPlayer2());
                if (player1Handler != null) {
                    player1Handler.out.println(message);
                }
                if (player2Handler != null) {
                    player2Handler.out.println(message);
                }
            } else {
                // 如果有sender，只发送给另一个玩家
                Socket receiver = sender.equals(room.getPlayer1()) ? room.getPlayer2() : room.getPlayer1();
                if (receiver != null) {
                    ClientHandler handler = clients.get(receiver);
                    if (handler != null) {
                        handler.out.println(message);
                    }
                }
            }
        }
        
        private void startGame(Room room) {
            room.setGameStarted(true);
            ClientHandler player1 = clients.get(room.getPlayer1());
            ClientHandler player2 = clients.get(room.getPlayer2());
            
            if (player1 != null) {
                player1.out.println("GAME_START|BLACK");
            }
            if (player2 != null) {
                player2.out.println("GAME_START|WHITE");
            }
            
            broadcastRoomList();
        }
    }
    
    public boolean isRunning() {
        return isRunning;
    }

    public void stop() {
        isRunning = false;
        try {
            if (serverSocket != null && !serverSocket.isClosed()) {
                serverSocket.close();
            }
            pool.shutdown();
        } catch (IOException e) {
            log("关闭服务器错误: " + e.getMessage());
        }
    }
    
    public void log(String message) {
        System.out.println(message);
    }
} 